﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Security.Cryptography;

namespace Redbrick.Silverlight.Common
{
	public static partial class Extentions
	{
		public static IEnumerable<T> ToEnumerable<T>(this Array target)
		{
			foreach (var item in target)
				yield return (T)item;
		}
        public static IList<T> Randomize<T>(this IList<T> source)
        {
           return source.Randomize(0);
        }

        public static IList<T> Randomize<T>(this IList<T> source, int skip)
        {
            RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
            int n = source.Count;
            while (n > skip)
            {
                byte[] box = new byte[1];
                
                do provider.GetBytes(box);
                while (!(box[0] < n * (Byte.MaxValue / n)));
                
                int k = (box[0] % n);

                if (n < skip) continue;
                if (k < skip) continue;

                n--;
                T value = source[k];
                source[k] = source[n];
                source[n] = value;
            }
            return source;
        }

		/// <summary>
		/// add a range to an observable collection
		/// </summary>
		public static ObservableCollection<_type> AddRange<_type>(this ObservableCollection<_type> oc, IEnumerable<_type> data)
		{
			foreach (_type cur in data)
				oc.Add(cur);
			return oc;
		}

		/// <summary>
		/// for each element in the OC, run the function
		/// </summary>
        //public static ObservableCollection<_type> ForEach<_type>(this ObservableCollection<_type> oc, Action<_type> action)
        //{
        //    foreach (_type cur in oc)
        //    {
        //        action(cur);
        //    }
        //    return oc;
        //}
        //public static ObservableCollection<_type> ForEach<_type>(this ObservableCollection<_type> oc, Action<int,_type> action)
        //{
        //    int ndx = 0;
        //    foreach (_type cur in oc)
        //    {
        //        action(ndx++,cur);
        //    }
        //    return oc;
        //}
     
        /// <summary>
		/// for each item in the IEnumerable, run the action 
		/// </summary>
		public static void ForEach<_type>(this IEnumerable<_type> itemList, Action<_type> action)
		{
            foreach (_type itm in itemList)
                action(itm);
        }
        public static void ForEach<_type>(this IEnumerable<_type> itemList, Action<int,_type> action)
        {
            int ndx = 0;
            foreach (_type itm in itemList)
                action(ndx++, itm);
        }
   
        /// <summary>
		/// for each item in the IEnumerable, run the action 
		/// </summary>
        public static void ForEach<_type>(this IEnumerable itemList, Action<_type> action)
        {
            itemList.Cast<_type>().ForEach(action);
        }
        public static void ForEach<_type>(this IEnumerable itemList, Action<int,_type> action)
        {
            itemList.Cast<_type>().ForEach(action);
        }

		/// <summary>
		/// convert the IEnumerable to an OC
		/// </summary>
		public static ObservableCollection<_type> ToObservableCollection<_type>(this IEnumerable<_type> items)
		{
            ObservableCollection<_type> oc = new ObservableCollection<_type>();
            oc.AddRange(items);
            return oc;
		}
		/// <summary>
		/// convert the IEnumerable to an OC
		/// </summary>
		public static ObservableCollection<_type> ToObservableCollection<_type>(this IEnumerable items)
		{
			ObservableCollection<_type> oc = new ObservableCollection<_type>();
			items.ForEach<_type>((itm) => oc.Add(itm));
			return oc;
		}

		/// <summary>
		/// search an IEnumerable by using a predicate
		/// </summary>
		public static bool Has<_type>(this IEnumerable<_type> items, Func<_type, bool> predicate)
		{
			if (items == null) return false;
			if (items.Count() == 0) return false;
			foreach (_type item in items)
				if (predicate(item)) return true;
			return false;
		}

		public static int FirstIndexOf<_type>(this IEnumerable<_type> source,Func<_type,bool> predicate)
		{
			int i = 0;
			foreach (_type item in source)
			{
				if (predicate(item)) return i;
				i++;
			}
			return -1;
		}

		/// <summary>
		/// swap two items in the same IList
		/// </summary>
		public static List<_type> Swap<_type>(this List<_type> source, int ndx1, int ndx2)
		{
			_type temp = source[ndx1];
			source[ndx1] = source[ndx2];
			source[ndx2] = temp;
			return source;
		}
		public static List<_type> Swap<_type>(this List<_type> source, _type itm1, _type itm2)
		{
			int ndx1 = source.IndexOf(itm1);
			int ndx2 = source.IndexOf(itm2);
			return source.Swap(ndx1, ndx2);
		}
	}
}
